home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / security / socks / rftp / ftp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-27  |  30.8 KB  |  1,470 lines

  1. /*
  2.  * Copyright (c) 1985, 1989 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. static char sccsid[] = "@(#)ftp.c    5.38 (Berkeley) 4/22/91";
  36. #endif /* not lint */
  37.  
  38. #include <sys/param.h>
  39. #include <sys/stat.h>
  40. #include <sys/ioctl.h>
  41. #include <sys/socket.h>
  42. #include <sys/time.h>
  43. #include <sys/file.h>
  44.  
  45. #include <netinet/in.h>
  46. #include <netinet/in_systm.h>
  47. #include <netinet/ip.h>
  48. #include <arpa/ftp.h>
  49. #include <arpa/telnet.h>
  50.  
  51. #include <stdio.h>
  52. #include <signal.h>
  53. #include <errno.h>
  54. #include <netdb.h>
  55. #include <fcntl.h>
  56. #include <pwd.h>
  57. #include <varargs.h>
  58.  
  59. #include "ftp_var.h"
  60.  
  61. struct    sockaddr_in hisctladdr;
  62. struct    sockaddr_in data_addr;
  63. int    data = -1;
  64. int    abrtflag = 0;
  65. int    ptflag = 0;
  66. struct    sockaddr_in myctladdr;
  67. uid_t    getuid();
  68. sig_t    lostpeer();
  69. off_t    restart_point = 0;
  70. unsigned long remoteAddr;        /* Socks */
  71.  
  72. extern char *strerror();
  73. extern int connected, errno;
  74.  
  75. FILE    *cin, *cout;
  76. FILE    *dataconn();
  77.  
  78. char *
  79. hookup(host, port)
  80.     char *host;
  81.     int port;
  82. {
  83.     register struct hostent *hp = 0;
  84.     int s, len, tos;
  85.     static char hostnamebuf[80];
  86.  
  87.     bzero((char *)&hisctladdr, sizeof (hisctladdr));
  88.     hisctladdr.sin_addr.s_addr = inet_addr(host);
  89.     if (hisctladdr.sin_addr.s_addr != -1) {
  90.         hisctladdr.sin_family = AF_INET;
  91.         (void) strncpy(hostnamebuf, host, sizeof(hostnamebuf));
  92.     } else {
  93.         hp = gethostbyname(host);
  94.         if (hp == NULL) {
  95.             fprintf(stderr, "ftp: %s: ", host);
  96.             herror((char *)NULL);
  97.             code = -1;
  98.             return((char *) 0);
  99.         }
  100.         hisctladdr.sin_family = hp->h_addrtype;
  101.         bcopy(hp->h_addr_list[0],
  102.             (caddr_t)&hisctladdr.sin_addr, hp->h_length);
  103.         (void) strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf));
  104.     }
  105.     hostname = hostnamebuf;
  106.     s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
  107.     if (s < 0) {
  108.         perror("ftp: socket");
  109.         code = -1;
  110.         return (0);
  111.     }
  112.     hisctladdr.sin_port = port;
  113.     while (Rconnect(s, (struct sockaddr *)&hisctladdr, sizeof (hisctladdr)) < 0) {
  114.         if (hp && hp->h_addr_list[1]) {
  115.             int oerrno = errno;
  116.             extern char *inet_ntoa();
  117.  
  118.             fprintf(stderr, "ftp: connect to address %s: ",
  119.                 inet_ntoa(hisctladdr.sin_addr));
  120.             errno = oerrno;
  121.             perror((char *) 0);
  122.             hp->h_addr_list++;
  123.             bcopy(hp->h_addr_list[0],
  124.                  (caddr_t)&hisctladdr.sin_addr, hp->h_length);
  125.             fprintf(stdout, "Trying %s...\n",
  126.                 inet_ntoa(hisctladdr.sin_addr));
  127.             (void) close(s);
  128.             s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
  129.             if (s < 0) {
  130.                 perror("ftp: socket");
  131.                 code = -1;
  132.                 return (0);
  133.             }
  134.             continue;
  135.         }
  136.         perror("ftp: connect");
  137.         code = -1;
  138.         goto bad;
  139.     }
  140.     remoteAddr = hisctladdr.sin_addr.s_addr;     /* Socks */
  141.     len = sizeof (myctladdr);
  142.     if (Rgetsockname(s, (struct sockaddr *)&myctladdr, &len) < 0) {
  143.         perror("ftp: getsockname");
  144.         code = -1;
  145.         goto bad;
  146.     }
  147. #ifdef IP_TOS
  148.     tos = IPTOS_LOWDELAY;
  149.     if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
  150.         perror("ftp: setsockopt TOS (ignored)");
  151. #endif
  152.     cin = fdopen(s, "r");
  153.     cout = fdopen(s, "w");
  154.     if (cin == NULL || cout == NULL) {
  155.         fprintf(stderr, "ftp: fdopen failed.\n");
  156.         if (cin)
  157.             (void) fclose(cin);
  158.         if (cout)
  159.             (void) fclose(cout);
  160.         code = -1;
  161.         goto bad;
  162.     }
  163.     if (verbose)
  164.         printf("Connected to %s.\n", hostname);
  165.     if (getreply(0) > 2) {     /* read startup message from server */
  166.         if (cin)
  167.             (void) fclose(cin);
  168.         if (cout)
  169.             (void) fclose(cout);
  170.         code = -1;
  171.         goto bad;
  172.     }
  173. #ifdef SO_OOBINLINE
  174.     {
  175.     int on = 1;
  176.  
  177.     if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on))
  178.         < 0 && debug) {
  179.             perror("ftp: setsockopt");
  180.         }
  181.     }
  182. #endif /* SO_OOBINLINE */
  183.  
  184.     return (hostname);
  185. bad:
  186.     (void) close(s);
  187.     return ((char *)0);
  188. }
  189.  
  190. login(host)
  191.     char *host;
  192. {
  193.     char tmp[80];
  194.     char *user, *pass, *acct, *getlogin(), *getpass();
  195.     int n, aflag = 0;
  196.  
  197.     user = pass = acct = 0;
  198.     if (ruserpass(host, &user, &pass, &acct) < 0) {
  199.         code = -1;
  200.         return(0);
  201.     }
  202.     while (user == NULL) {
  203.         char *myname = getlogin();
  204.  
  205.         if (myname == NULL) {
  206.             struct passwd *pp = getpwuid(getuid());
  207.  
  208.             if (pp != NULL)
  209.                 myname = pp->pw_name;
  210.         }
  211.         if (myname)
  212.             printf("Name (%s:%s): ", host, myname);
  213.         else
  214.             printf("Name (%s): ", host);
  215.         (void) fgets(tmp, sizeof(tmp) - 1, stdin);
  216.         tmp[strlen(tmp) - 1] = '\0';
  217.         if (*tmp == '\0')
  218.             user = myname;
  219.         else
  220.             user = tmp;
  221.     }
  222.     n = command("USER %s", user);
  223.     if (n == CONTINUE) {
  224.         if (pass == NULL)
  225.             pass = getpass("Password:");
  226.         n = command("PASS %s", pass);
  227.     }
  228.     if (n == CONTINUE) {
  229.         aflag++;
  230.         acct = getpass("Account:");
  231.         n = command("ACCT %s", acct);
  232.     }
  233.     if (n != COMPLETE) {
  234.         fprintf(stderr, "Login failed.\n");
  235.         return (0);
  236.     }
  237.     if (!aflag && acct != NULL)
  238.         (void) command("ACCT %s", acct);
  239.     if (proxy)
  240.         return(1);
  241.     for (n = 0; n < macnum; ++n) {
  242.         if (!strcmp("init", macros[n].mac_name)) {
  243.             (void) strcpy(line, "$init");
  244.             makeargv();
  245.             domacro(margc, margv);
  246.             break;
  247.         }
  248.     }
  249.     return (1);
  250. }
  251.  
  252. void
  253. cmdabort()
  254. {
  255.     extern jmp_buf ptabort;
  256.  
  257.     printf("\n");
  258.     (void) fflush(stdout);
  259.     abrtflag++;
  260.     if (ptflag)
  261.         longjmp(ptabort,1);
  262. }
  263.  
  264. /*VARARGS*/
  265. command(va_alist)
  266. va_dcl
  267. {
  268.     va_list ap;
  269.     char *fmt;
  270.     int r;
  271.     sig_t oldintr;
  272.     void cmdabort();
  273.  
  274.     abrtflag = 0;
  275.     if (debug) {
  276.         printf("---> ");
  277.         va_start(ap);
  278.         fmt = va_arg(ap, char *);
  279.         if (strncmp("PASS ", fmt, 5) == 0)
  280.             printf("PASS XXXX");
  281.         else 
  282.             vfprintf(stdout, fmt, ap);
  283.         va_end(ap);
  284.         printf("\n");
  285.         (void) fflush(stdout);
  286.     }
  287.     if (cout == NULL) {
  288.         perror ("No control connection for command");
  289.         code = -1;
  290.         return (0);
  291.     }
  292.     oldintr = signal(SIGINT, cmdabort);
  293.     va_start(ap);
  294.     fmt = va_arg(ap, char *);
  295.     vfprintf(cout, fmt, ap);
  296.     va_end(ap);
  297.     fprintf(cout, "\r\n");
  298.     (void) fflush(cout);
  299.     cpend = 1;
  300.     r = getreply(!strcmp(fmt, "QUIT"));
  301.     if (abrtflag && oldintr != SIG_IGN)
  302.         (*oldintr)(SIGINT);
  303.     (void) signal(SIGINT, oldintr);
  304.     return(r);
  305. }
  306.  
  307. char reply_string[BUFSIZ];        /* last line of previous reply */
  308.  
  309. #include <ctype.h>
  310.  
  311. getreply(expecteof)
  312.     int expecteof;
  313. {
  314.     register int c, n;
  315.     register int dig;
  316.     register char *cp;
  317.     int originalcode = 0, continuation = 0;
  318.     sig_t oldintr;
  319.     int pflag = 0;
  320.     char *pt = pasv;
  321.     void cmdabort();
  322.  
  323.     oldintr = signal(SIGINT, cmdabort);
  324.     for (;;) {
  325.         dig = n = code = 0;
  326.         cp = reply_string;
  327.         while ((c = getc(cin)) != '\n') {
  328.             if (c == IAC) {     /* handle telnet commands */
  329.                 switch (c = getc(cin)) {
  330.                 case WILL:
  331.                 case WONT:
  332.                     c = getc(cin);
  333.                     fprintf(cout, "%c%c%c", IAC, DONT, c);
  334.                     (void) fflush(cout);
  335.                     break;
  336.                 case DO:
  337.                 case DONT:
  338.                     c = getc(cin);
  339.                     fprintf(cout, "%c%c%c", IAC, WONT, c);
  340.                     (void) fflush(cout);
  341.                     break;
  342.                 default:
  343.                     break;
  344.                 }
  345.                 continue;
  346.             }
  347.             dig++;
  348.             if (c == EOF) {
  349.                 if (expecteof) {
  350.                     (void) signal(SIGINT,oldintr);
  351.                     code = 221;
  352.                     return (0);
  353.                 }
  354.                 lostpeer();
  355.                 if (verbose) {
  356.                     printf("421 Service not available, remote server has closed connection\n");
  357.                     (void) fflush(stdout);
  358.                 }
  359.                 code = 421;
  360.                 return(4);
  361.             }
  362.             if (c != '\r' && (verbose > 0 ||
  363.                 (verbose > -1 && n == '5' && dig > 4))) {
  364.                 if (proxflag &&
  365.                    (dig == 1 || dig == 5 && verbose == 0))
  366.                     printf("%s:",hostname);
  367.                 (void) putchar(c);
  368.             }
  369.             if (dig < 4 && isdigit(c))
  370.                 code = code * 10 + (c - '0');
  371.             if (!pflag && code == 227)
  372.                 pflag = 1;
  373.             if (dig > 4 && pflag == 1 && isdigit(c))
  374.                 pflag = 2;
  375.             if (pflag == 2) {
  376.                 if (c != '\r' && c != ')')
  377.                     *pt++ = c;
  378.                 else {
  379.                     *pt = '\0';
  380.                     pflag = 3;
  381.                 }
  382.             }
  383.             if (dig == 4 && c == '-') {
  384.                 if (continuation)
  385.                     code = 0;
  386.                 continuation++;
  387.             }
  388.             if (n == 0)
  389.                 n = c;
  390.             if (cp < &reply_string[sizeof(reply_string) - 1])
  391.                 *cp++ = c;
  392.         }
  393.         if (verbose > 0 || verbose > -1 && n == '5') {
  394.             (void) putchar(c);
  395.             (void) fflush (stdout);
  396.         }
  397.         if (continuation && code != originalcode) {
  398.             if (originalcode == 0)
  399.                 originalcode = code;
  400.             continue;
  401.         }
  402.         *cp = '\0';
  403.         if (n != '1')
  404.             cpend = 0;
  405.         (void) signal(SIGINT,oldintr);
  406.         if (code == 421 || originalcode == 421)
  407.             lostpeer();
  408.         if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN)
  409.             (*oldintr)(SIGINT);
  410.         return (n - '0');
  411.     }
  412. }
  413.  
  414. empty(mask, sec)
  415.     struct fd_set *mask;
  416.     int sec;
  417. {
  418.     struct timeval t;
  419.  
  420.     t.tv_sec = (long) sec;
  421.     t.tv_usec = 0;
  422.     return(select(32, mask, (struct fd_set *) 0, (struct fd_set *) 0, &t));
  423. }
  424.  
  425. jmp_buf    sendabort;
  426.  
  427. void
  428. abortsend()
  429. {
  430.  
  431.     mflag = 0;
  432.     abrtflag = 0;
  433.     printf("\nsend aborted\nwaiting for remote to finish abort\n");
  434.     (void) fflush(stdout);
  435.     longjmp(sendabort, 1);
  436. }
  437.  
  438. #define HASHBYTES 1024
  439.  
  440. sendrequest(cmd, local, remote, printnames)
  441.     char *cmd, *local, *remote;
  442.     int printnames;
  443. {
  444.     struct stat st;
  445.     struct timeval start, stop;
  446.     register int c, d;
  447.     FILE *fin, *dout = 0, *popen();
  448.     int (*closefunc)(), pclose(), fclose();
  449.     sig_t oldintr, oldintp;
  450.     long bytes = 0, hashbytes = HASHBYTES;
  451.     char *lmode, buf[BUFSIZ], *bufp;
  452.     void abortsend();
  453.  
  454.     if (verbose && printnames) {
  455.         if (local && *local != '-')
  456.             printf("local: %s ", local);
  457.         if (remote)
  458.             printf("remote: %s\n", remote);
  459.     }
  460.     if (proxy) {
  461.         proxtrans(cmd, local, remote);
  462.         return;
  463.     }
  464.     if (curtype != type)
  465.         changetype(type, 0);
  466.     closefunc = NULL;
  467.     oldintr = NULL;
  468.     oldintp = NULL;
  469.     lmode = "w";
  470.     if (setjmp(sendabort)) {
  471.         while (cpend) {
  472.             (void) getreply(0);
  473.         }
  474.         if (data >= 0) {
  475.             (void) close(data);
  476.             data = -1;
  477.         }
  478.         if (oldintr)
  479.             (void) signal(SIGINT,oldintr);
  480.         if (oldintp)
  481.             (void) signal(SIGPIPE,oldintp);
  482.         code = -1;
  483.         return;
  484.     }
  485.     oldintr = signal(SIGINT, abortsend);
  486.     if (strcmp(local, "-") == 0)
  487.         fin = stdin;
  488.     else if (*local == '|') {
  489.         oldintp = signal(SIGPIPE,SIG_IGN);
  490.         fin = popen(local + 1, "r");
  491.         if (fin == NULL) {
  492.             perror(local + 1);
  493.             (void) signal(SIGINT, oldintr);
  494.             (void) signal(SIGPIPE, oldintp);
  495.             code = -1;
  496.             return;
  497.         }
  498.         closefunc = pclose;
  499.     } else {
  500.         fin = fopen(local, "r");
  501.         if (fin == NULL) {
  502.             fprintf(stderr, "local: %s: %s\n", local,
  503.                 strerror(errno));
  504.             (void) signal(SIGINT, oldintr);
  505.             code = -1;
  506.             return;
  507.         }
  508.         closefunc = fclose;
  509.         if (fstat(fileno(fin), &st) < 0 ||
  510.             (st.st_mode&S_IFMT) != S_IFREG) {
  511.             fprintf(stdout, "%s: not a plain file.\n", local);
  512.             (void) signal(SIGINT, oldintr);
  513.             fclose(fin);
  514.             code = -1;
  515.             return;
  516.         }
  517.     }
  518.     if (initconn()) {
  519.         (void) signal(SIGINT, oldintr);
  520.         if (oldintp)
  521.             (void) signal(SIGPIPE, oldintp);
  522.         code = -1;
  523.         if (closefunc != NULL)
  524.             (*closefunc)(fin);
  525.         return;
  526.     }
  527.     if (setjmp(sendabort))
  528.         goto abort;
  529.  
  530.     if (restart_point &&
  531.         (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) {
  532.         if (fseek(fin, (long) restart_point, 0) < 0) {
  533.             fprintf(stderr, "local: %s: %s\n", local,
  534.                 strerror(errno));
  535.             restart_point = 0;
  536.             if (closefunc != NULL)
  537.                 (*closefunc)(fin);
  538.             return;
  539.         }
  540.         if (command("REST %ld", (long) restart_point)
  541.             != CONTINUE) {
  542.             restart_point = 0;
  543.             if (closefunc != NULL)
  544.                 (*closefunc)(fin);
  545.             return;
  546.         }
  547.         restart_point = 0;
  548.         lmode = "r+w";
  549.     }
  550.     if (remote) {
  551.         if (command("%s %s", cmd, remote) != PRELIM) {
  552.             (void) signal(SIGINT, oldintr);
  553.             if (oldintp)
  554.                 (void) signal(SIGPIPE, oldintp);
  555.             if (closefunc != NULL)
  556.                 (*closefunc)(fin);
  557.             return;
  558.         }
  559.     } else
  560.         if (command("%s", cmd) != PRELIM) {
  561.             (void) signal(SIGINT, oldintr);
  562.             if (oldintp)
  563.                 (void) signal(SIGPIPE, oldintp);
  564.             if (closefunc != NULL)
  565.                 (*closefunc)(fin);
  566.             return;
  567.         }
  568.     dout = dataconn(lmode);
  569.     if (dout == NULL)
  570.         goto abort;
  571.     (void) gettimeofday(&start, (struct timezone *)0);
  572.     oldintp = signal(SIGPIPE, SIG_IGN);
  573.     switch (curtype) {
  574.  
  575.     case TYPE_I:
  576.     case TYPE_L:
  577.         errno = d = 0;
  578.         while ((c = read(fileno(fin), buf, sizeof (buf))) > 0) {
  579.             bytes += c;
  580.             for (bufp = buf; c > 0; c -= d, bufp += d)
  581.                 if ((d = write(fileno(dout), bufp, c)) <= 0)
  582.                     break;
  583.             if (hash) {
  584.                 while (bytes >= hashbytes) {
  585.                     (void) putchar('#');
  586.                     hashbytes += HASHBYTES;
  587.                 }
  588.                 (void) fflush(stdout);
  589.             }
  590.         }
  591.         if (hash && bytes > 0) {
  592.             if (bytes < HASHBYTES)
  593.                 (void) putchar('#');
  594.             (void) putchar('\n');
  595.             (void) fflush(stdout);
  596.         }
  597.         if (c < 0)
  598.             fprintf(stderr, "local: %s: %s\n", local,
  599.                 strerror(errno));
  600.         if (d < 0) {
  601.             if (errno != EPIPE) 
  602.                 perror("netout");
  603.             bytes = -1;
  604.         }
  605.         break;
  606.  
  607.     case TYPE_A:
  608.         while ((c = getc(fin)) != EOF) {
  609.             if (c == '\n') {
  610.                 while (hash && (bytes >= hashbytes)) {
  611.                     (void) putchar('#');
  612.                     (void) fflush(stdout);
  613.                     hashbytes += HASHBYTES;
  614.                 }
  615.                 if (ferror(dout))
  616.                     break;
  617.                 (void) putc('\r', dout);
  618.                 bytes++;
  619.             }
  620.             (void) putc(c, dout);
  621.             bytes++;
  622.     /*        if (c == '\r') {                  */
  623.     /*        (void)    putc('\0', dout);  /* this violates rfc */
  624.     /*            bytes++;                */
  625.     /*        }                                      */    
  626.         }
  627.         if (hash) {
  628.             if (bytes < hashbytes)
  629.                 (void) putchar('#');
  630.             (void) putchar('\n');
  631.             (void) fflush(stdout);
  632.         }
  633.         if (ferror(fin))
  634.             fprintf(stderr, "local: %s: %s\n", local,
  635.                 strerror(errno));
  636.         if (ferror(dout)) {
  637.             if (errno != EPIPE)
  638.                 perror("netout");
  639.             bytes = -1;
  640.         }
  641.         break;
  642.     }
  643.     (void) gettimeofday(&stop, (struct timezone *)0);
  644.     if (closefunc != NULL)
  645.         (*closefunc)(fin);
  646.     (void) fclose(dout);
  647.     (void) getreply(0);
  648.     (void) signal(SIGINT, oldintr);
  649.     if (oldintp)
  650.         (void) signal(SIGPIPE, oldintp);
  651.     if (bytes > 0)
  652.         ptransfer("sent", bytes, &start, &stop);
  653.     return;
  654. abort:
  655.     (void) gettimeofday(&stop, (struct timezone *)0);
  656.     (void) signal(SIGINT, oldintr);
  657.     if (oldintp)
  658.         (void) signal(SIGPIPE, oldintp);
  659.     if (!cpend) {
  660.         code = -1;
  661.         return;
  662.     }
  663.     if (data >= 0) {
  664.         (void) close(data);
  665.         data = -1;
  666.     }
  667.     if (dout)
  668.         (void) fclose(dout);
  669.     (void) getreply(0);
  670.     code = -1;
  671.     if (closefunc != NULL && fin != NULL)
  672.         (*closefunc)(fin);
  673.     if (bytes > 0)
  674.         ptransfer("sent", bytes, &start, &stop);
  675. }
  676.  
  677. jmp_buf    recvabort;
  678.  
  679. void
  680. abortrecv()
  681. {
  682.  
  683.     mflag = 0;
  684.     abrtflag = 0;
  685.     printf("\nreceive aborted\nwaiting for remote to finish abort\n");
  686.     (void) fflush(stdout);
  687.     longjmp(recvabort, 1);
  688. }
  689.  
  690. recvrequest(cmd, local, remote, lmode, printnames)
  691.     char *cmd, *local, *remote, *lmode;
  692. {
  693.     FILE *fout, *din = 0, *popen();
  694.     int (*closefunc)(), pclose(), fclose();
  695.     sig_t oldintr, oldintp;
  696.     int is_retr, tcrflag, bare_lfs = 0;
  697.     char *gunique();
  698.     static int bufsize;
  699.     static char *buf;
  700.     long bytes = 0, hashbytes = HASHBYTES;
  701.     register int c, d;
  702.     struct timeval start, stop;
  703.     struct stat st;
  704.     off_t lseek();
  705.     void abortrecv();
  706.     char *malloc();
  707.  
  708.     is_retr = strcmp(cmd, "RETR") == 0;
  709.     if (is_retr && verbose && printnames) {
  710.         if (local && *local != '-')
  711.             printf("local: %s ", local);
  712.         if (remote)
  713.             printf("remote: %s\n", remote);
  714.     }
  715.     if (proxy && is_retr) {
  716.         proxtrans(cmd, local, remote);
  717.         return;
  718.     }
  719.     closefunc = NULL;
  720.     oldintr = NULL;
  721.     oldintp = NULL;
  722.     tcrflag = !crflag && is_retr;
  723.     if (setjmp(recvabort)) {
  724.         while (cpend) {
  725.             (void) getreply(0);
  726.         }
  727.         if (data >= 0) {
  728.             (void) close(data);
  729.             data = -1;
  730.         }
  731.         if (oldintr)
  732.             (void) signal(SIGINT, oldintr);
  733.         code = -1;
  734.         return;
  735.     }
  736.     oldintr = signal(SIGINT, abortrecv);
  737.     if (strcmp(local, "-") && *local != '|') {
  738.         if (access(local, 2) < 0) {
  739.             char *dir = rindex(local, '/');
  740.  
  741.             if (errno != ENOENT && errno != EACCES) {
  742.                 fprintf(stderr, "local: %s: %s\n", local,
  743.                     strerror(errno));
  744.                 (void) signal(SIGINT, oldintr);
  745.                 code = -1;
  746.                 return;
  747.             }
  748.             if (dir != NULL)
  749.                 *dir = 0;
  750.             d = access(dir ? local : ".", 2);
  751.             if (dir != NULL)
  752.                 *dir = '/';
  753.             if (d < 0) {
  754.                 fprintf(stderr, "local: %s: %s\n", local,
  755.                     strerror(errno));
  756.                 (void) signal(SIGINT, oldintr);
  757.                 code = -1;
  758.                 return;
  759.             }
  760.             if (!runique && errno == EACCES &&
  761.                 chmod(local, 0600) < 0) {
  762.                 fprintf(stderr, "local: %s: %s\n", local,
  763.                     strerror(errno));
  764.                 (void) signal(SIGINT, oldintr);
  765.                 (void) signal(SIGINT, oldintr);
  766.                 code = -1;
  767.                 return;
  768.             }
  769.             if (runique && errno == EACCES &&
  770.                (local = gunique(local)) == NULL) {
  771.                 (void) signal(SIGINT, oldintr);
  772.                 code = -1;
  773.                 return;
  774.             }
  775.         }
  776.         else if (runique && (local = gunique(local)) == NULL) {
  777.             (void) signal(SIGINT, oldintr);
  778.             code = -1;
  779.             return;
  780.         }
  781.     }
  782.     if (!is_retr) {
  783.         if (curtype != TYPE_A)
  784.             changetype(TYPE_A, 0);
  785.     } else if (curtype != type)
  786.         changetype(type, 0);
  787.     if (initconn()) {
  788.         (void) signal(SIGINT, oldintr);
  789.         code = -1;
  790.         return;
  791.     }
  792.     if (setjmp(recvabort))
  793.         goto abort;
  794.     if (is_retr && restart_point &&
  795.         command("REST %ld", (long) restart_point) != CONTINUE)
  796.         return;
  797.     if (remote) {
  798.         if (command("%s %s", cmd, remote) != PRELIM) {
  799.             (void) signal(SIGINT, oldintr);
  800.             return;
  801.         }
  802.     } else {
  803.         if (command("%s", cmd) != PRELIM) {
  804.             (void) signal(SIGINT, oldintr);
  805.             return;
  806.         }
  807.     }
  808.     din = dataconn("r");
  809.     if (din == NULL)
  810.         goto abort;
  811.     if (strcmp(local, "-") == 0)
  812.         fout = stdout;
  813.     else if (*local == '|') {
  814.         oldintp = signal(SIGPIPE, SIG_IGN);
  815.         fout = popen(local + 1, "w");
  816.         if (fout == NULL) {
  817.             perror(local+1);
  818.             goto abort;
  819.         }
  820.         closefunc = pclose;
  821.     } else {
  822.         fout = fopen(local, lmode);
  823.         if (fout == NULL) {
  824.             fprintf(stderr, "local: %s: %s\n", local,
  825.                 strerror(errno));
  826.             goto abort;
  827.         }
  828.         closefunc = fclose;
  829.     }
  830.     if (fstat(fileno(fout), &st) < 0 || st.st_blksize == 0)
  831.         st.st_blksize = BUFSIZ;
  832.     if (st.st_blksize > bufsize) {
  833.         if (buf)
  834.             (void) free(buf);
  835.         buf = malloc((unsigned)st.st_blksize);
  836.         if (buf == NULL) {
  837.             perror("malloc");
  838.             bufsize = 0;
  839.             goto abort;
  840.         }
  841.         bufsize = st.st_blksize;
  842.     }
  843.     (void) gettimeofday(&start, (struct timezone *)0);
  844.     switch (curtype) {
  845.  
  846.     case TYPE_I:
  847.     case TYPE_L:
  848.         if (restart_point &&
  849.             lseek(fileno(fout), (long) restart_point, L_SET) < 0) {
  850.             fprintf(stderr, "local: %s: %s\n", local,
  851.                 strerror(errno));
  852.             if (closefunc != NULL)
  853.                 (*closefunc)(fout);
  854.             return;
  855.         }
  856.         errno = d = 0;
  857.         while ((c = read(fileno(din), buf, bufsize)) > 0) {
  858.             if ((d = write(fileno(fout), buf, c)) != c)
  859.                 break;
  860.             bytes += c;
  861.             if (hash) {
  862.                 while (bytes >= hashbytes) {
  863.                     (void) putchar('#');
  864.                     hashbytes += HASHBYTES;
  865.                 }
  866.                 (void) fflush(stdout);
  867.             }
  868.         }
  869.         if (hash && bytes > 0) {
  870.             if (bytes < HASHBYTES)
  871.                 (void) putchar('#');
  872.             (void) putchar('\n');
  873.             (void) fflush(stdout);
  874.         }
  875.         if (c < 0) {
  876.             if (errno != EPIPE)
  877.                 perror("netin");
  878.             bytes = -1;
  879.         }
  880.         if (d < c) {
  881.             if (d < 0)
  882.                 fprintf(stderr, "local: %s: %s\n", local,
  883.                     strerror(errno));
  884.             else
  885.                 fprintf(stderr, "%s: short write\n", local);
  886.         }
  887.         break;
  888.  
  889.     case TYPE_A:
  890.         if (restart_point) {
  891.             register int i, n, ch;
  892.  
  893.             if (fseek(fout, 0L, L_SET) < 0)
  894.                 goto done;
  895.             n = restart_point;
  896.             for (i = 0; i++ < n;) {
  897.                 if ((ch = getc(fout)) == EOF)
  898.                     goto done;
  899.                 if (ch == '\n')
  900.                     i++;
  901.             }
  902.             if (fseek(fout, 0L, L_INCR) < 0) {
  903. done:
  904.                 fprintf(stderr, "local: %s: %s\n", local,
  905.                     strerror(errno));
  906.                 if (closefunc != NULL)
  907.                     (*closefunc)(fout);
  908.                 return;
  909.             }
  910.         }
  911.         while ((c = getc(din)) != EOF) {
  912.             if (c == '\n')
  913.                 bare_lfs++;
  914.             while (c == '\r') {
  915.                 while (hash && (bytes >= hashbytes)) {
  916.                     (void) putchar('#');
  917.                     (void) fflush(stdout);
  918.                     hashbytes += HASHBYTES;
  919.                 }
  920.                 bytes++;
  921.                 if ((c = getc(din)) != '\n' || tcrflag) {
  922.                     if (ferror(fout))
  923.                         goto break2;
  924.                     (void) putc('\r', fout);
  925.                     if (c == '\0') {
  926.                         bytes++;
  927.                         goto contin2;
  928.                     }
  929.                     if (c == EOF)
  930.                         goto contin2;
  931.                 }
  932.             }
  933.             (void) putc(c, fout);
  934.             bytes++;
  935.     contin2:    ;
  936.         }
  937. break2:
  938.         if (bare_lfs) {
  939.             printf("WARNING! %d bare linefeeds received in ASCII mode\n", bare_lfs);
  940.             printf("File may not have transferred correctly.\n");
  941.         }
  942.         if (hash) {
  943.             if (bytes < hashbytes)
  944.                 (void) putchar('#');
  945.             (void) putchar('\n');
  946.             (void) fflush(stdout);
  947.         }
  948.         if (ferror(din)) {
  949.             if (errno != EPIPE)
  950.                 perror("netin");
  951.             bytes = -1;
  952.         }
  953.         if (ferror(fout))
  954.             fprintf(stderr, "local: %s: %s\n", local,
  955.                 strerror(errno));
  956.         break;
  957.     }
  958.     if (closefunc != NULL)
  959.         (*closefunc)(fout);
  960.     (void) signal(SIGINT, oldintr);
  961.     if (oldintp)
  962.         (void) signal(SIGPIPE, oldintp);
  963.     (void) gettimeofday(&stop, (struct timezone *)0);
  964.     (void) fclose(din);
  965.     (void) getreply(0);
  966.     if (bytes > 0 && is_retr)
  967.         ptransfer("received", bytes, &start, &stop);
  968.     return;
  969. abort:
  970.  
  971. /* abort using RFC959 recommended IP,SYNC sequence  */
  972.  
  973.     (void) gettimeofday(&stop, (struct timezone *)0);
  974.     if (oldintp)
  975.         (void) signal(SIGPIPE, oldintr);
  976.     (void) signal(SIGINT, SIG_IGN);
  977.     if (!cpend) {
  978.         code = -1;
  979.         (void) signal(SIGINT, oldintr);
  980.         return;
  981.     }
  982.  
  983.     abort_remote(din);
  984.     code = -1;
  985.     if (data >= 0) {
  986.         (void) close(data);
  987.         data = -1;
  988.     }
  989.     if (closefunc != NULL && fout != NULL)
  990.         (*closefunc)(fout);
  991.     if (din)
  992.         (void) fclose(din);
  993.     if (bytes > 0)
  994.         ptransfer("received", bytes, &start, &stop);
  995.     (void) signal(SIGINT, oldintr);
  996. }
  997.  
  998. /*
  999.  * Need to start a listen on the data channel before we send the command,
  1000.  * otherwise the server's connect may fail.
  1001.  */
  1002. initconn()
  1003. {
  1004.     register char *p, *a;
  1005.     int result, len, tmpno = 0;
  1006.     int on = 1;
  1007.  
  1008. noport:
  1009.     data_addr = myctladdr;
  1010.     if (sendport)
  1011.         data_addr.sin_port = 0;    /* let system pick one */ 
  1012.     if (data != -1)
  1013.         (void) close(data);
  1014.     data = socket(AF_INET, SOCK_STREAM, 0);
  1015.     if (data < 0) {
  1016.         perror("ftp: socket");
  1017.         if (tmpno)
  1018.             sendport = 1;
  1019.         return (1);
  1020.     }
  1021.     if (!sendport)
  1022.         if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) {
  1023.             perror("ftp: setsockopt (reuse address)");
  1024.             goto bad;
  1025.         }
  1026.     if (Rbind(data, (struct sockaddr *)&data_addr, sizeof (data_addr), remoteAddr) < 0) {
  1027.         perror("ftp: bind");
  1028.         goto bad;
  1029.     }
  1030.     if (options & SO_DEBUG &&
  1031.         setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0)
  1032.         perror("ftp: setsockopt (ignored)");
  1033.     len = sizeof (data_addr);
  1034.     if (Rgetsockname(data, (struct sockaddr *)&data_addr, &len) < 0) {
  1035.         perror("ftp: getsockname");
  1036.         goto bad;
  1037.     }
  1038.     if (Rlisten(data, 1) < 0)
  1039.         perror("ftp: listen");
  1040.     if (sendport) {
  1041.         a = (char *)&data_addr.sin_addr;
  1042.         p = (char *)&data_addr.sin_port;
  1043. #define    UC(b)    (((int)b)&0xff)
  1044.         result =
  1045.             command("PORT %d,%d,%d,%d,%d,%d",
  1046.               UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
  1047.               UC(p[0]), UC(p[1]));
  1048.         if (result == ERROR && sendport == -1) {
  1049.             sendport = 0;
  1050.             tmpno = 1;
  1051.             goto noport;
  1052.         }
  1053.         return (result != COMPLETE);
  1054.     }
  1055.     if (tmpno)
  1056.         sendport = 1;
  1057. #ifdef IP_TOS
  1058.     on = IPTOS_THROUGHPUT;
  1059.     if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0)
  1060.         perror("ftp: setsockopt TOS (ignored)");
  1061. #endif
  1062.     return (0);
  1063. bad:
  1064.     (void) close(data), data = -1;
  1065.     if (tmpno)
  1066.         sendport = 1;
  1067.     return (1);
  1068. }
  1069.  
  1070. FILE *
  1071. dataconn(lmode)
  1072.     char *lmode;
  1073. {
  1074.     struct sockaddr_in from;
  1075.     int s, fromlen = sizeof (from), tos;
  1076.  
  1077.     s = Raccept(data, (struct sockaddr *) &from, &fromlen);
  1078.     if (s < 0) {
  1079.         perror("ftp: accept");
  1080.         (void) close(data), data = -1;
  1081.         return (NULL);
  1082.     }
  1083.     (void) close(data);
  1084.     data = s;
  1085. #ifdef IP_TOS
  1086.     tos = IPTOS_THROUGHPUT;
  1087.     if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
  1088.         perror("ftp: setsockopt TOS (ignored)");
  1089. #endif
  1090.     return (fdopen(data, lmode));
  1091. }
  1092.  
  1093. ptransfer(direction, bytes, t0, t1)
  1094.     char *direction;
  1095.     long bytes;
  1096.     struct timeval *t0, *t1;
  1097. {
  1098.     struct timeval td;
  1099.     float s, bs;
  1100.  
  1101.     if (verbose) {
  1102.         tvsub(&td, t1, t0);
  1103.         s = td.tv_sec + (td.tv_usec / 1000000.);
  1104. #define    nz(x)    ((x) == 0 ? 1 : (x))
  1105.         bs = bytes / nz(s);
  1106.         printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n",
  1107.             bytes, direction, s, bs / 1024.);
  1108.     }
  1109. }
  1110.  
  1111. /*tvadd(tsum, t0)
  1112.     struct timeval *tsum, *t0;
  1113. {
  1114.  
  1115.     tsum->tv_sec += t0->tv_sec;
  1116.     tsum->tv_usec += t0->tv_usec;
  1117.     if (tsum->tv_usec > 1000000)
  1118.         tsum->tv_sec++, tsum->tv_usec -= 1000000;
  1119. } */
  1120.  
  1121. tvsub(tdiff, t1, t0)
  1122.     struct timeval *tdiff, *t1, *t0;
  1123. {
  1124.  
  1125.     tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
  1126.     tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
  1127.     if (tdiff->tv_usec < 0)
  1128.         tdiff->tv_sec--, tdiff->tv_usec += 1000000;
  1129. }
  1130.  
  1131. void
  1132. psabort()
  1133. {
  1134.     extern int abrtflag;
  1135.  
  1136.     abrtflag++;
  1137. }
  1138.  
  1139. pswitch(flag)
  1140.     int flag;
  1141. {
  1142.     extern int proxy, abrtflag;
  1143.     sig_t oldintr;
  1144.     static struct comvars {
  1145.         int connect;
  1146.         char name[MAXHOSTNAMELEN];
  1147.         struct sockaddr_in mctl;
  1148.         struct sockaddr_in hctl;
  1149.         FILE *in;
  1150.         FILE *out;
  1151.         int tpe;
  1152.         int curtpe;
  1153.         int cpnd;
  1154.         int sunqe;
  1155.         int runqe;
  1156.         int mcse;
  1157.         int ntflg;
  1158.         char nti[17];
  1159.         char nto[17];
  1160.         int mapflg;
  1161.         char mi[MAXPATHLEN];
  1162.         char mo[MAXPATHLEN];
  1163.     } proxstruct, tmpstruct;
  1164.     struct comvars *ip, *op;
  1165.  
  1166.     abrtflag = 0;
  1167.     oldintr = signal(SIGINT, psabort);
  1168.     if (flag) {
  1169.         if (proxy)
  1170.             return;
  1171.         ip = &tmpstruct;
  1172.         op = &proxstruct;
  1173.         proxy++;
  1174.     } else {
  1175.         if (!proxy)
  1176.             return;
  1177.         ip = &proxstruct;
  1178.         op = &tmpstruct;
  1179.         proxy = 0;
  1180.     }
  1181.     ip->connect = connected;
  1182.     connected = op->connect;
  1183.     if (hostname) {
  1184.         (void) strncpy(ip->name, hostname, sizeof(ip->name) - 1);
  1185.         ip->name[strlen(ip->name)] = '\0';
  1186.     } else
  1187.         ip->name[0] = 0;
  1188.     hostname = op->name;
  1189.     ip->hctl = hisctladdr;
  1190.     hisctladdr = op->hctl;
  1191.     ip->mctl = myctladdr;
  1192.     myctladdr = op->mctl;
  1193.     ip->in = cin;
  1194.     cin = op->in;
  1195.     ip->out = cout;
  1196.     cout = op->out;
  1197.     ip->tpe = type;
  1198.     type = op->tpe;
  1199.     ip->curtpe = curtype;
  1200.     curtype = op->curtpe;
  1201.     ip->cpnd = cpend;
  1202.     cpend = op->cpnd;
  1203.     ip->sunqe = sunique;
  1204.     sunique = op->sunqe;
  1205.     ip->runqe = runique;
  1206.     runique = op->runqe;
  1207.     ip->mcse = mcase;
  1208.     mcase = op->mcse;
  1209.     ip->ntflg = ntflag;
  1210.     ntflag = op->ntflg;
  1211.     (void) strncpy(ip->nti, ntin, 16);
  1212.     (ip->nti)[strlen(ip->nti)] = '\0';
  1213.     (void) strcpy(ntin, op->nti);
  1214.     (void) strncpy(ip->nto, ntout, 16);
  1215.     (ip->nto)[strlen(ip->nto)] = '\0';
  1216.     (void) strcpy(ntout, op->nto);
  1217.     ip->mapflg = mapflag;
  1218.     mapflag = op->mapflg;
  1219.     (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1);
  1220.     (ip->mi)[strlen(ip->mi)] = '\0';
  1221.     (void) strcpy(mapin, op->mi);
  1222.     (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1);
  1223.     (ip->mo)[strlen(ip->mo)] = '\0';
  1224.     (void) strcpy(mapout, op->mo);
  1225.     (void) signal(SIGINT, oldintr);
  1226.     if (abrtflag) {
  1227.         abrtflag = 0;
  1228.         (*oldintr)(SIGINT);
  1229.     }
  1230. }
  1231.  
  1232. jmp_buf ptabort;
  1233. int ptabflg;
  1234.  
  1235. void
  1236. abortpt()
  1237. {
  1238.     printf("\n");
  1239.     (void) fflush(stdout);
  1240.     ptabflg++;
  1241.     mflag = 0;
  1242.     abrtflag = 0;
  1243.     longjmp(ptabort, 1);
  1244. }
  1245.  
  1246. proxtrans(cmd, local, remote)
  1247.     char *cmd, *local, *remote;
  1248. {
  1249.     sig_t oldintr;
  1250.     int secndflag = 0, prox_type, nfnd;
  1251.     extern jmp_buf ptabort;
  1252.     char *cmd2;
  1253.     struct fd_set mask;
  1254.     void abortpt();
  1255.  
  1256.     if (strcmp(cmd, "RETR"))
  1257.         cmd2 = "RETR";
  1258.     else
  1259.         cmd2 = runique ? "STOU" : "STOR";
  1260.     if ((prox_type = type) == 0) {
  1261.         if (unix_server && unix_proxy)
  1262.             prox_type = TYPE_I;
  1263.         else
  1264.             prox_type = TYPE_A;
  1265.     }
  1266.     if (curtype != prox_type)
  1267.         changetype(prox_type, 1);
  1268.     if (command("PASV") != COMPLETE) {
  1269.         printf("proxy server does not support third party transfers.\n");
  1270.         return;
  1271.     }
  1272.     pswitch(0);
  1273.     if (!connected) {
  1274.         printf("No primary connection\n");
  1275.         pswitch(1);
  1276.         code = -1;
  1277.         return;
  1278.     }
  1279.     if (curtype != prox_type)
  1280.         changetype(prox_type, 1);
  1281.     if (command("PORT %s", pasv) != COMPLETE) {
  1282.         pswitch(1);
  1283.         return;
  1284.     }
  1285.     if (setjmp(ptabort))
  1286.         goto abort;
  1287.     oldintr = signal(SIGINT, abortpt);
  1288.     if (command("%s %s", cmd, remote) != PRELIM) {
  1289.         (void) signal(SIGINT, oldintr);
  1290.         pswitch(1);
  1291.         return;
  1292.     }
  1293.     sleep(2);
  1294.     pswitch(1);
  1295.     secndflag++;
  1296.     if (command("%s %s", cmd2, local) != PRELIM)
  1297.         goto abort;
  1298.     ptflag++;
  1299.     (void) getreply(0);
  1300.     pswitch(0);
  1301.     (void) getreply(0);
  1302.     (void) signal(SIGINT, oldintr);
  1303.     pswitch(1);
  1304.     ptflag = 0;
  1305.     printf("local: %s remote: %s\n", local, remote);
  1306.     return;
  1307. abort:
  1308.     (void) signal(SIGINT, SIG_IGN);
  1309.     ptflag = 0;
  1310.     if (strcmp(cmd, "RETR") && !proxy)
  1311.         pswitch(1);
  1312.     else if (!strcmp(cmd, "RETR") && proxy)
  1313.         pswitch(0);
  1314.     if (!cpend && !secndflag) {  /* only here if cmd = "STOR" (proxy=1) */
  1315.         if (command("%s %s", cmd2, local) != PRELIM) {
  1316.             pswitch(0);
  1317.             if (cpend)
  1318.                 abort_remote((FILE *) NULL);
  1319.         }
  1320.         pswitch(1);
  1321.         if (ptabflg)
  1322.             code = -1;
  1323.         (void) signal(SIGINT, oldintr);
  1324.         return;
  1325.     }
  1326.     if (cpend)
  1327.         abort_remote((FILE *) NULL);
  1328.     pswitch(!proxy);
  1329.     if (!cpend && !secndflag) {  /* only if cmd = "RETR" (proxy=1) */
  1330.         if (command("%s %s", cmd2, local) != PRELIM) {
  1331.             pswitch(0);
  1332.             if (cpend)
  1333.                 abort_remote((FILE *) NULL);
  1334.             pswitch(1);
  1335.             if (ptabflg)
  1336.                 code = -1;
  1337.             (void) signal(SIGINT, oldintr);
  1338.             return;
  1339.         }
  1340.     }
  1341.     if (cpend)
  1342.         abort_remote((FILE *) NULL);
  1343.     pswitch(!proxy);
  1344.     if (cpend) {
  1345.         FD_ZERO(&mask);
  1346.         FD_SET(fileno(cin), &mask);
  1347.         if ((nfnd = empty(&mask, 10)) <= 0) {
  1348.             if (nfnd < 0) {
  1349.                 perror("abort");
  1350.             }
  1351.             if (ptabflg)
  1352.                 code = -1;
  1353.             lostpeer();
  1354.         }
  1355.         (void) getreply(0);
  1356.         (void) getreply(0);
  1357.     }
  1358.     if (proxy)
  1359.         pswitch(0);
  1360.     pswitch(1);
  1361.     if (ptabflg)
  1362.         code = -1;
  1363.     (void) signal(SIGINT, oldintr);
  1364. }
  1365.  
  1366. reset()
  1367. {
  1368.     struct fd_set mask;
  1369.     int nfnd = 1;
  1370.  
  1371.     FD_ZERO(&mask);
  1372.     while (nfnd > 0) {
  1373.         FD_SET(fileno(cin), &mask);
  1374.         if ((nfnd = empty(&mask,0)) < 0) {
  1375.             perror("reset");
  1376.             code = -1;
  1377.             lostpeer();
  1378.         }
  1379.         else if (nfnd) {
  1380.             (void) getreply(0);
  1381.         }
  1382.     }
  1383. }
  1384.  
  1385. char *
  1386. gunique(local)
  1387.     char *local;
  1388. {
  1389.     static char new[MAXPATHLEN];
  1390.     char *cp = rindex(local, '/');
  1391.     int d, count=0;
  1392.     char ext = '1';
  1393.  
  1394.     if (cp)
  1395.         *cp = '\0';
  1396.     d = access(cp ? local : ".", 2);
  1397.     if (cp)
  1398.         *cp = '/';
  1399.     if (d < 0) {
  1400.         fprintf(stderr, "local: %s: %s\n", local, strerror(errno));
  1401.         return((char *) 0);
  1402.     }
  1403.     (void) strcpy(new, local);
  1404.     cp = new + strlen(new);
  1405.     *cp++ = '.';
  1406.     while (!d) {
  1407.         if (++count == 100) {
  1408.             printf("runique: can't find unique file name.\n");
  1409.             return((char *) 0);
  1410.         }
  1411.         *cp++ = ext;
  1412.         *cp = '\0';
  1413.         if (ext == '9')
  1414.             ext = '0';
  1415.         else
  1416.             ext++;
  1417.         if ((d = access(new, 0)) < 0)
  1418.             break;
  1419.         if (ext != '0')
  1420.             cp--;
  1421.         else if (*(cp - 2) == '.')
  1422.             *(cp - 1) = '1';
  1423.         else {
  1424.             *(cp - 2) = *(cp - 2) + 1;
  1425.             cp--;
  1426.         }
  1427.     }
  1428.     return(new);
  1429. }
  1430.  
  1431. abort_remote(din)
  1432. FILE *din;
  1433. {
  1434.     char buf[BUFSIZ];
  1435.     int nfnd;
  1436.     struct fd_set mask;
  1437.  
  1438.     /*
  1439.      * send IAC in urgent mode instead of DM because 4.3BSD places oob mark
  1440.      * after urgent byte rather than before as is protocol now
  1441.      */
  1442.     sprintf(buf, "%c%c%c", IAC, IP, IAC);
  1443.     if (send(fileno(cout), buf, 3, MSG_OOB) != 3)
  1444.         perror("abort");
  1445.     fprintf(cout,"%cABOR\r\n", DM);
  1446.     (void) fflush(cout);
  1447.     FD_ZERO(&mask);
  1448.     FD_SET(fileno(cin), &mask);
  1449.     if (din) { 
  1450.         FD_SET(fileno(din), &mask);
  1451.     }
  1452.     if ((nfnd = empty(&mask, 10)) <= 0) {
  1453.         if (nfnd < 0) {
  1454.             perror("abort");
  1455.         }
  1456.         if (ptabflg)
  1457.             code = -1;
  1458.         lostpeer();
  1459.     }
  1460.     if (din && FD_ISSET(fileno(din), &mask)) {
  1461.         while (read(fileno(din), buf, BUFSIZ) > 0)
  1462.             /* LOOP */;
  1463.     }
  1464.     if (getreply(0) == ERROR && code == 552) {
  1465.         /* 552 needed for nic style abort */
  1466.         (void) getreply(0);
  1467.     }
  1468.     (void) getreply(0);
  1469. }
  1470.